home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BMUG Revelations
/
BMUG Revelations.toast
/
Utilities
/
Network
/
Asynchronous Networking
/
ULACS.p
< prev
Wrap
Text File
|
1990-12-21
|
26KB
|
753 lines
{ Copyright © 1988 - 1990 by Apple Computer, Inc. All rights reserved. }
unit ULACS;
interface
uses
{ • MacApp }
UMacApp,
{ • Building Blocks }
UPrinting, UGridView, UTEView, UDialog,
{ • Required for this unit's interface }
Sane,
{ • Implementation use }
ToolUtils, Fonts, Resources, Packages, Notification, AppleTalk, ADSP;
const
kSignature = 'rumo'; { Application signature }
kLACSSettings = 'rums'; { File type for settings/messages file. }
kApplicationVersion = '1.1'; { Application version for Params query replies. }
{ Periodic function times: }
{ About box "psssts": }
kPssstInitial = 30;
kPssstInactive = 30;
kPssstActive = 30;
{ Document saver: }
kDocSaverInitial = 60*60*30;
kDocSaverInactive = 60*60*30;
kDocSaverActive = 30;
{ LACS expirer: }
kExpirerInitial = 30;
kExpirerInactive = 30;
kExpirerActive = 30;
{ Zone lookup: }
kZoneLookupInitial = 0;
kZoneLookupInactive = 60*60*60*4;
kZoneLookupActive = 30;
{ Node lookup: }
kNodeLookupInitial = 60*8;
kNodeLookupFastInactive = 60*8;
kNodeLookupSlowInactive = 60*60*20;
kNodeLookupActive = 30;
{ Gossipee: }
kGossipeeInitial = 0;
kGossipeeInactive = 60*60 + 13;
kGossipeeActive = 30;
{ Gossiper: }
kGossiperInitial = 1300;
kGossiperInactive = 60*30 + 27;
kGossiperActive = 30;
kMessagesWindow = 1000; { Resource # for messages window. }
kNewWindow = 1001; { Resource # for New window. }
kStatusWindow = 1002; { Resource # for Status window. }
kAboutWindow = 1003; { Resource # for About... window. }
kPreferencesWindow = 1004; { Resource # for preferences dialog. }
kMySmallIcon = 1000; { Resource # for small icon for notification manager. }
kOurMemReserve = 20480; { How much memory to reserve above the MacApp reserve. }
kMaxMessageSize = 500; { Maximum size of message text. }
kSettingsFileSTR = 1000; { Resource # for STR for default settings file name. }
phInvalidSettings = 1000; { Resource # for invalid settings file alert. }
phNoADSP = 1001; { Resource # for no ADSP alert. }
phAreYouSure = 1002; { Resource # for querying if the user is really sure about the post. }
phLegal = 1003; { Resource # for opening splash screen for legal disclaimers. }
phNoPhase2 = 1004; { Resource # for no AppleTalk phase 2 alert. }
kPsstHead = 1000; { Resource # for "pssst" balloon icon. }
kNoPsstHead = 1001; { Resource # for balloon with no "pssst" icon. }
kSettingsVersion = 107; { Version of settings file we recognize. }
cMessagesWindow = 1000; { Command # for Messages Window. }
cNewWindow = 1001; { Command # for New Window. }
cStatusWindow = 1002; { Command # for Status Window. }
cMarkAllRead = 1003; { Command # for Mark All Messages Read. }
cClearMessages = 1004; { Command # for Delete All Messages. }
cPreferences = 1005; { Command # for Preferences... }
kStatStrings = 1000; { Resource # for STR# strings for status display: }
kChooserName = -16096; { Resource # for Chooser name STR. }
kStatBored = 1; { "Bored and idle..." }
kStatNewMessage = 2; { "Adding new message..." }
kStatZoneUpdate = 3; { "Updating zone list..." }
kStatNodeUpdate = 4; { "Updating node list..." }
kStatGossiping = 5; { "Initiating gossip..." }
kStatIncomingConnect = 6; { "Gossiping..." }
kStatusBoredRate = 5*60; { How long to leave status up before going bored again (in ticks). }
{ Network stuff: }
{ csCodes for new .XPP driver calls: }
xCall = 246;
{ xppSubCodes: }
zipGetLocalZones = 5;
zipGetZoneList = 6;
zipGetMyZone = 7;
type
{ Offsets for xCall queue elements: }
xCallParam =
packed record
qLink: QElemPtr;
qType: INTEGER;
ioTrap: INTEGER;
ioCmdAddr: Ptr;
ioCompletion: ProcPtr;
ioResult: OsErr;
ioNamePtr: StringPtr;
ioVRefNum: INTEGER;
ioRefNum: INTEGER;
csCode: INTEGER;
xppSubCode: INTEGER;
xppTimeOut: Byte;
xppRetry: Byte;
filler: INTEGER;
zipBuffPtr: Ptr;
zipNumZones: INTEGER;
zipLastFlag: INTEGER;
zipInfoField: packed array[1..70] of Byte;
end;
xCallPtr = ^xCallParam;
const
kXPPTimeOutVal = 3; { Re-try XPP attempt every 3 seconds. }
kXPPRetryCount = 5; { For five times. }
kZonesBufferSize = 578; { Size of buffer for zone names. }
kMaxZones = 100; { Maximum number of zones to handle. }
kMaxNodes = 10; { Maximum number of nodes to gossip with at once. }
kNBPTimeOutVal = 8; { Re-try NBP PLookupName every 64/60ths seconds. }
kNBPRetryCount = 5; { For five times. }
kMaxLookupNames = 100; { Maximum number of names to lookup. }
kLookupBufferSize = kMaxLookupNames*(sizeof(EntityName)+sizeof(AddrBlock)+4);
kLACS = 'LACS'; { NBP type for LACSs. }
kADSPSendBufSize = 1024; { Buffer size for ADSP sends. }
kADSPRecvBufSize = 1024; { Buffer size for ADSP receives. }
kADSPMaxCommand = 1024; { Buffer size for message exchange protocol command. }
kNormalFilter = 'Rumor'; { Normal value for the filter field in messages. }
kNormalType = 'General'; { Normal value for the type field in messages. }
kSignatureSeparator = '∫'; { Character used to separate the signature from the message text. }
kTab = 9; { ASCII tab. }
kReturn = 13; { ASCII carriage return. }
type
TLACSApplication = object(TApplication)
function TLACSApplication.DoMakeDocument(itsCmdNumber: CmdNumber): TDocument; override;
{ Make a new document. }
function TLACSApplication.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; override;
{ Handle menu commands. }
procedure TLACSApplication.DoSetupMenus; override;
{ Enable the appropriate menus. }
procedure TLACSApplication.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TLACSApplication.Free; override;
{ Free the application. }
procedure TLACSApplication.ILACSApplication(itsMainFileType: OSType);
{ Initializes the application and globals. }
procedure TLACSApplication.Terminate; override;
{ Clean up when application is terminated. }
end;
{ Document-wide configuration: }
ForwardOn = (kForwardManually, kForwardIfSigned, kForwardAlways);
SignatureFrom = (kNoSignature, kSignatureFromChooser, kSignatureFromUser);
ConfigSettings =
record
inZoneSearch: integer; { Will look outside our zone with 1/gInZoneSearch probability. }
push: boolean; { Actively connect when a hot message is available. }
pull: boolean; { Connect and ask for hot messages even if we don't have any. }
pullOnLess: integer; { Pull if there's less than gPullOnLess messages in our list. }
count: boolean; { Decide on cooling based on count rather than probability. }
countValue: integer; { Number of counts or kill with 1/gCountValue probability. }
feedback: boolean; { Use information on whether the message has been seen by other end. }
delayBase: longInt; { Seconds for base of delay calculations. }
delayExp: longInt; { Exponent for delay calcs: (badPasses*delayBase)^delayExp. }
expireIn: longInt; { Distance in future to expire messages. }
defaultFilter: Str32; { Default filter string. }
defaultType: Str32; { Default type string. }
forwarding: ForwardOn; { When to forward messages. }
signature: SignatureFrom; { Where to get the signature. }
userSignature: Str32; { Signature the user entered. }
end;
{ Saved display state: }
DisplayState =
record
messagesWindPos: Point; { Position of Messages window. }
messagesWindShown: boolean; { Whether Messages window is shown. }
notifyOnNew: boolean; { Whether the "Notify on new" checkbox is set. }
newWindPos: Point; { Position of New window. }
newWindShown: boolean; { Whether New window is shown. }
statusWindPos: Point; { Position of Status window. }
statusWindShown: boolean; { Whether Status window is shown. }
totalMessages: longInt; { Total message count. }
passedMessages: longInt; { Total passed on message count. }
end;
TLACSDocument = object(TDocument)
fMessages: TList; { All known messages. }
fMessagesWindow: TMessagesWindow; { Window to display messages. }
fNewWindow: TNewWindow; { Window to create new messages. }
fStatusWindow: TStatusWindow; { Window to display status. }
fDocumentSaver: TDocumentSaver; { Periodic document saver object. }
fMessagesExpirator: TMessagesExpirator; { Message expiration object. }
fZoneLooker: TZoneLookup; { Zone lookup object. }
fNodeLooker: TNodeLookup; { Node lookup object. }
fGossiper: TGossip; { Gossiper (spreader). }
fGossipee: TGossip; { Gossipee (receiver). }
fConfig: ConfigSettings; { Distribution algorithm parameters. }
fUseDisplayState: boolean; { True if we're to use the display state record. }
fDisplayState: DisplayState; { The positions of the windows. }
procedure TLACSDocument.CheckFreeSpace;
{ Check the amount of free space available in memory, and free messages if necessary to make room. }
procedure TLACSDocument.CloseView(aView: TView); override;
{ Close a window in the document. }
procedure TLACSDocument.DoInitialState; override;
{ Set up the initial state of the document. }
procedure TLACSDocument.DoMakeViews(forPrinting: boolean); override;
{ Create views to display the document. }
function TLACSDocument.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; override;
{ Handle menu commands. }
procedure TLACSDocument.DoNeedDiskSpace(var dataForkBytes, rsrcForkBytes: longInt); override;
{ Computer how much disk space is needed to save the document to disk. }
procedure TLACSDocument.DoRead(aRefNum: integer; rsrcExists, forPrinting: boolean); override;
{ Read the document from disk. }
procedure TLACSDocument.DoSetupMenus; override;
{ Enable the appropriate menus. }
procedure TLACSDocument.DoWrite(aRefNum: integer; makingCopy: boolean); override;
{ Write the document to disk. }
procedure TLACSDocument.ExpireMessages;
{ Check for expired messages, and dump them if they are expired. }
procedure TLACSDocument.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TLACSDocument.Free; override;
{ Free the document. }
function TLACSDocument.GetHotMessage: TMessage;
{ Find a hot message, if there are any. }
procedure TLACSDocument.GetPreferences;
{ Query the user for his preferences. }
function TLACSDocument.GetRandomMessage: TMessage;
{ Find a message at random. }
function TLACSDocument.GetMessage(f: Str32; t: Str32; h: Handle): TMessage;
{ Get the message that corresponds to the filter/type/handle given. }
function TLACSDocument.HandleIncomingCommand(theData: Ptr; theSz: longInt): longInt;
{ Parse and process an incoming command. }
procedure TLACSDocument.ILACSDocument;
{ Intialize the document. }
procedure TLACSDocument.MarkAllAsRead;
{ Mark all messages as read. }
procedure TLACSDocument.NewMessage(ru: boolean; f: Str32; t: Str32; h: Handle; sd: longInt; ed: longInt;
alwaysForward: boolean);
{ Enter a new message into the document. }
procedure TLACSDocument.ParseAsParams(h: Handle);
{ Interpret the data in the handle as a configuration setting string. }
procedure TLACSDocument.ShowWindows; override;
{ Display windows (or not) as appropriate. }
end;
{ Format of a message when saved to disk (discluding text): }
SavedMessage =
record
hot: boolean;
successfulPasses: integer;
badPasses: integer;
filter: Str32;
rType: Str32;
startDate: longInt;
expireDate: longInt;
lastMessaged: longInt;
inReadList: boolean;
forward: boolean;
end;
TMessage = object(TObject)
fDocument: TLACSDocument; { The document containing the message. }
fHot: boolean; { Whether the message is currently hot. }
fSuccessfulPasses: integer; { How many times we've successfully passed the message on. }
fBadPasses: integer; { How many times we've unsuccessfully tried to pass it on. }
fFilter: Str32; { The message's filter field. }
fType: Str32; { The message's type field. }
fText: Handle; { The body of the message. }
fStartDate: longInt; { The origination date of the message. }
fExpireDate: longInt; { The expiration date of the message. }
fLastMessaged: longInt; { The last time we passed it on, or tried to. }
fForward: boolean; { Whether this message has been approved for forwarding. }
procedure TMessage.AsString(var aString: Str255);
{ Return a string that represents the message (for display lists). }
function TMessage.BuildMessageCommand(var theData: Ptr): longInt;
{ Build a message command into the buffer pointed to by theData, incrementing theData as we go,
and return the size of the command built. }
procedure TMessage.DoNeedDiskSpace(var dataForkBytes, rsrcForkBytes: longInt);
{ Return the amount of disk space needed to save this message. }
procedure TMessage.FailedPass;
{ Factor in one more bad pass attempt. }
procedure TMessage.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TMessage.Free; override;
{ Free the message object. }
procedure TMessage.IMessage(aDoc: TLACSDocument; isRead: boolean; f: Str32; t: Str32; newText: Handle;
sd: longInt; ed: longInt);
{ Initialize a message object. }
procedure TMessage.IMessageFromFile(aDoc: TLACSDocument; aRefNum: integer);
{ Initialize a message object from a file. }
function TMessage.IsHot: boolean;
{ Return true if this message is still hot, and if enough time has passed for it to be spread again. }
procedure TMessage.MarkAsRead;
{ Mark this message as read. }
procedure TMessage.ParseAsParams;
{ Parse ourself as algorithm parameters. }
procedure TMessage.SuccessfullPass;
{ Factor in one more successfull pass attempt. }
procedure TMessage.UpdateHotness;
{ Update the temperature of this message. }
procedure TMessage.WriteToFile(aRefNum: integer);
{ Save this message to disk. }
end;
TDisplayList = object(TSortedList)
fDocument: TLACSDocument; { Our document. }
fView: TTextListView; { The corresponding text list view. }
procedure TDisplayList.AtDelete(index: ArrayIndex); override;
{ Delete the entry at index. }
function TDisplayList.Compare(item1, item2: TObject): CompareResult; override;
{ Compare two objects. }
procedure TDisplayList.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TDisplayList.FreeAll; override;
{ Free everything. }
procedure TDisplayList.IDisplayList(theDoc: TLACSDocument; theView: TMessageListView);
{ Initialize the list. }
procedure TDisplayList.Insert(item: TObject); override;
{ Insert an item into the list. }
procedure TDisplayList.Invalidate(o: TObject);
{ Invalidate the displayed object. }
procedure TDisplayList.Select(o: TObject);
{ Select the displayed object. }
end;
TMessagesWindow = object(TWindow)
fNotification: ^NMRec; { Notification manager record. }
fUnread: TDisplayList; { List of unread messages. }
fRead: TDisplayList; { List of read messages. }
fNotify: TCheckBox; { Checkbox that indicates whether to notify on new messages. }
fShow: TTEView; { View to display the message text in. }
fOriginated: TStaticText; { View for origination date. }
fExpires: TStaticText; { View for expiration date. }
fForward: TCheckbox; { Whether to forward this message on. }
procedure TMessagesWindow.ClearCurrent;
{ Clear out the selected message display. }
procedure TMessagesWindow.DisplayMessage(r: TMessage);
{ Display message r. }
procedure TMessagesWindow.DoChoice(origView: TView; itsChoice: integer); override;
{ Handle button hits, etc. }
procedure TMessagesWindow.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TMessagesWindow.FindSubviews;
{ Lookup all our subviews for later. }
procedure TMessagesWindow.Free; override;
{ Free the window. }
procedure TMessagesWindow.KillNotify;
{ Take away the Notification Manager notification. }
procedure TMessagesWindow.Notify;
{ Notify the user via the Notification Manager. }
end;
TNewWindow = object(TWindow)
fInput: TTEView; { View for typing message body. }
fSpread: TButton; { Send Message button. }
fMonth: TPopup; { Expiration month pop-up. }
fDay: TPopup; { Expiration day pop-up. }
fYear: TStaticText; { Expiration year display (computed). }
fSignature: TStaticText; { The message signature. }
procedure TNewWindow.DoChoice(origView: TView; itsChoice: integer); override;
{ Handle button hits, etc. }
function TNewWindow.DoKeyCommand(ch: char; aKeyCode: integer;
var info: EventInfo): TCommand; override;
{ Handle keyboard events. }
function TNewWindow.ExpireExpired: boolean;
{ Check if we need to reset the expiration date. }
procedure TNewWindow.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TNewWindow.FindSubviews;
{ Lookup all our subviews for later. }
function TNewWindow.GetExpire: longInt;
{ Get the expiration date. }
procedure TNewWindow.GetSetExpire;
{ Get and set the expiration date (corrects for odd month/day combinations, etc. }
procedure TNewWindow.GetSignature;
{ Figure out the current signature. }
procedure TNewWindow.ResetExpire;
{ Reset the expiration date display. }
procedure TNewWindow.ResetIfExpired;
{ Reset the expiration date if the current one is expired. }
procedure TNewWindow.SetExpire(t: longInt);
{ Set the expiration date. }
end;
TStatusWindow = object(TWindow)
fTotalMessages: TNumberText; { Total messages display. }
fTotalPassed: TNumberText; { Total passed on messages display. }
fHotMessages: TNumberText; { Current hot messages display. }
fColdMessages: TNumberText; { Current cold messages display. }
fGossipWith: array [1..kMaxNodes] of TStaticText; { Gossiping with... display. }
fStatus: TStaticText; { Statis display. }
fLastStatusChange: longInt; { Last status change time. }
procedure TStatusWindow.Bored;
{ Change status to "bored and idle..." }
procedure TStatusWindow.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TStatusWindow.FindSubviews;
{ Lookup all our subviews for later. }
procedure TStatusWindow.IncColdMessages(i: integer);
{ Increment the current cold messages count by i. }
procedure TStatusWindow.IncHotMessages(i: integer);
{ Increment the current hot messages count by i. }
procedure TStatusWindow.IncTotalPassed(i: integer);
{ Increment the total messages passed on count by i. }
procedure TStatusWindow.IncTotalMessages(i: integer);
{ Increment the total messages seen count by i. }
procedure TStatusWindow.SetStatus(statNum: integer);
{ Change the status display. }
procedure TStatusWindow.UpdateGossipWith;
{ Update the display of who we're gossiping with. }
end;
TMessageListView = object(TTextListView)
fWindow: TMessagesWindow; { The window we're in. }
fList: TDisplayList; { The cooresponding list of messages. }
function TMessageListView.DoMouseCommand(var theMouse: Point; var info: EventInfo;
var hysteresis: Point): TCommand; override;
{ Handle mouse events. }
procedure TMessageListView.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TMessageListView.GetItemText(anItem: integer; var aString: Str255); override;
{ Retrieve the text for a particular item. }
end;
{ Valid states for TPeriodic's fState: }
PeriodicStates = (kPeriodicInactive, kPeriodicWaiting, kPeriodicActive);
TPeriodic = object(TEvtHandler)
fInactiveIdle: longInt; { How long to idle between activates. }
fActiveIdle: longInt; { How long to idle between checks for async completion. }
fState: PeriodicStates; { The current state. }
procedure TPeriodic.Activate;
{ Start a periodic activity. }
function TPeriodic.DoIdle(phase: IdlePhase): boolean; override;
{ Internal method -- idle the object. }
procedure TPeriodic.DoIt;
{ Handle the results of an async operation. }
procedure TPeriodic.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TPeriodic.Free; override;
{ Free the object. }
procedure TPeriodic.IPeriodic(initialIdle, inactiveIdle, activeIdle: longInt);
{ Initialize the object. }
procedure TPeriodic.Kick;
{ Start things up even if it isn't normally time yet. }
procedure TPeriodic.Waiting;
{ Test for async completion. }
end;
TPssst = object(TPeriodic)
procedure TPssst.Activate; override;
{ Update the about box. }
end;
TMessagesExpirator = object(TPeriodic)
fDocument: TLACSDocument; { The document we're expiring. }
procedure TMessagesExpirator.Activate; override;
{ Expire message. }
procedure TMessagesExpirator.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TMessagesExpirator.IMessagesExpirator(aDoc: TLACSDocument;
initialIdle, inactiveIdle, activeIdle: longInt);
{ Initialize messages expirer. }
end;
TDocumentSaver = object(TPeriodic)
fDocument: TLACSDocument; { The document we're saving. }
procedure TDocumentSaver.Activate; override;
{ Get ready to save. }
procedure TDocumentSaver.DoIt; override;
{ Save the document. }
procedure TDocumentSaver.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TDocumentSaver.IDocumentSaver(aDoc: TLACSDocument;
initialIdle, inactiveIdle, activeIdle: longInt);
{ Initialize the document saver. }
procedure TDocumentSaver.Waiting; override;
{ Wait until we're in the foreground. }
end;
TZoneLookup = object(TPeriodic)
fDocument: TLACSDocument; { The document we're looking up for. }
fZoneCount: integer; { How many zones we've found. }
fXPPPBPtr: xCallPtr; { XPP parameter block. }
fZonesBuffer: Ptr; { Input buffer. }
fOurZone: Str32; { The name of our own zone. }
fZones: array [1..kMaxZones] of Str32; { Zone names. }
procedure TZoneLookup.Activate; override;
{ Start a zone list lookup. }
procedure TZoneLookup.DoIt; override;
{ Process returned zone list. }
function TZoneLookup.GetRandomZone: Str32;
{ Pick a random zone from the list and return it. }
procedure TZoneLookup.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TZoneLookup.Free; override;
{ Free the zone lookup object. }
procedure TZoneLookup.IZoneLookup(aDoc: TLACSDocument; initialIdle, inactiveIdle, activeIdle: longInt);
{ Initialize the zone lookup object. }
procedure TZoneLookup.Waiting; override;
{ Wait for the zone lookup to complete. }
end;
TNodeLookup = object(TPeriodic)
fDocument: TLACSDocument; { The document we're looking up for. }
fSlowIdle: longInt; { Slow idling speed. }
fFastIdle: longInt; { Fast idling speed. }
fNodeCount: integer; { How many nodes we've found. }
fNameBuffer: Ptr; { Input buffer pointer. }
fpBlock: MPPPBPtr; { IO block pointer. }
fLookupBuf: Ptr; { Lookup buffer pointer. }
fZone: Str32; { The zone we're currently looking in. }
fNodes: array [1..kMaxNodes] of EntityName; { Nodes we've found. }
fAddrs: array [1..kMaxNodes] of AddrBlock; { Addresses we've found. }
procedure TNodeLookup.Activate; override;
{ Start a node lookup. }
procedure TNodeLookup.DoIt; override;
{ Process the results of a node lookup. }
procedure TNodeLookup.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TNodeLookup.Free; override;
{ Free the node lookup object. }
function TNodeLookup.GetRandomNode(var addr: AddrBlock): boolean;
{ Pick a random node from the list and return it. GetRandomNode itself returns true if we had a node to return. }
procedure TNodeLookup.INodeLookup(aDoc: TLACSDocument; initialIdle, fastIdle, slowIdle, activeIdle: longInt);
{ Initialize the node lookup object. }
procedure TNodeLookup.Waiting; override;
{ Wait for a node lookup to complete. }
end;
TGossip = object(TPeriodic)
fDocument: TLACSDocument; { The document we're gossiping in. }
fOutgoing: boolean; { Whether this is an outgoing gossiper. }
fDidPull: boolean; { Whether we just did a pull. }
fADSPSocket: integer; { Our socket number. }
fADSP: DSPPBPtr; { The ADSP IO block pointer. }
fCcbPtr: Ptr; { CCB for ADSP. }
fSendQueue: Ptr; { Send queue for ADSP. }
fRecvQueue: Ptr; { Receive queue for ADSP. }
fAttnPtr: Ptr; { Attn ptr for ADSP. }
fADSPData: Ptr; { The data buffer pointer. }
fNTE: ^NamesTableEntry; { Our names table entry. }
procedure TGossip.Activate; override;
{ Start a new gossip session (outgoing only). }
procedure TGossip.DoIt; override;
{ Handle new input. }
procedure TGossip.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
fieldType: integer)); override;
procedure TGossip.Free; override;
{ Free the gossip object. }
procedure TGossip.IGossip(aDoc: TLACSDocument; outgoing: boolean; initialIdle, inactiveIdle, activeIdle: longInt);
{ Initialize the gossip object. }
procedure TGossip.PassiveOpen;
{ Do a passive connection open. }
procedure TGossip.ResetConnection;
{ Reset the connection. }
procedure TGossip.Waiting; override;
{ Wait for more input or a connection to open. }
end;
implementation
{$I ULACS.inc1.p}
end.